package com.lyj.thread.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 10张车票，3个人抢票，每张票只能卖一次
 */
public class ReentrantLockDemo {

    public static int num;
    boolean flag = true;

    int cunt = 10;

    /**
     * new ReentrantLock()：默认非公平锁
     * new ReentrantLock(true)：创建公平锁
     */
    ReentrantLock lock = new ReentrantLock(true);

    public static void main(String[] args) throws InterruptedException {
        ReentrantLockDemo memo = new ReentrantLockDemo();
        MyThread t1 = new MyThread(memo);
        MyThread t2 = new MyThread(memo);
        MyThread t3 = new MyThread(memo);
        t1.start();
        t2.start();
        t3.start();
        // 测试可重入
//        MyThreadReentrant t = new MyThreadReentrant(memo.lock);
//        new Thread(t).start();

        // 测试可响应中断
//        InterruptThread interruptThread0 = new InterruptThread(memo.lock);
//        InterruptThread interruptThread1 = new InterruptThread(memo.lock);
//        interruptThread0.start();
//        TimeUnit.MILLISECONDS.sleep(1000);
//        interruptThread1.start();
//        // 中断获取锁
//        System.out.println(interruptThread1.getName() + "执行 interrupt() ");
//        interruptThread1.interrupt();
    }
}

class MyThread extends Thread {
    ReentrantLockDemo memo;

    public MyThread(ReentrantLockDemo memo) {
        this.memo = memo;
    }

    @Override
    public void run() {
        while (memo.flag) {
            try {
                Thread.sleep(500);
                extracted();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * 售票
     */
    private void extracted() {
        // 加锁
        memo.lock.lock();
        try {
            if (memo.lock.isHeldByCurrentThread()) {
                if (memo.cunt <= 0) {
                    memo.flag = false;
                    System.out.println(Thread.currentThread().getName() + "票已售罄");
                } else {
                    System.out.println(Thread.currentThread().getName() + "售出第" + memo.cunt + "张票");
                    memo.cunt--;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            memo.lock.unlock();
        }
    }


}

/**
 * ReentrantLock ；可重入锁
 * 之所以称之为重⼊锁，就是⼀个线程允许反复进⼊
 */
class MyThreadReentrant implements Runnable {

    private ReentrantLock lock;

    public MyThreadReentrant(ReentrantLock lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            lock.lock();
            try {
                ReentrantLockDemo.num++;
            } finally {
                System.out.println(111111);
                lock.unlock();
            }

        }
    }
}


/**
 * ReentrantLock：响应中断锁
 */
class InterruptThread extends Thread {
    private ReentrantLock lock;

    public InterruptThread(ReentrantLock lock) {
        this.lock = lock;
    }

    @Override
    public void run() {
        try {
            // 获取可响应中断锁
            lock.lockInterruptibly();
            System.out.println(Thread.currentThread().getName() + "加锁成功。");
            TimeUnit.MILLISECONDS.sleep(6000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } finally {
            lock.unlock();
        }
    }
}

